package site.tuluan.sp4j.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Map;

/**
 * HTTP工具类
 *
 * @author tuluan
 */
public class HttpUtils {
    public static final Logger log = LoggerFactory.getLogger(HttpUtils.class);

    public static final String METHOD_GET = "GET";

    public static final String METHOD_POST = "POST";

    public static final String CONTENT_TYPE_APPLICATION_JSON = "application/json";

    private static final HttpClient client = HttpClient.newBuilder().followRedirects(HttpClient.Redirect.NORMAL).build();

    /**
     * 发送GET请求
     * @param url 请求URL
     * @return 返回结果
     */
    public static String sendGet(String url) {
        return sendGet(url, StringUtils.EMPTY);
    }

    /**
     * 发送GET请求
     * @param url 请求URL
     * @param paramMap 请求参数
     * @return 返回结果
     */
    public static String sendGet(String url, Map<String, String> paramMap) {
        StringBuilder sb = new StringBuilder();
        if (paramMap != null && !paramMap.isEmpty()) {
            paramMap.forEach((k, v) -> sb.append(k).append("=").append(v).append("&"));
        }

        return sendGet(url, sb.substring(0, sb.length() - 1));
    }

    /**
     * 发送GET请求
     * @param url 请求URL
     * @param param 请求参数 形式: name1=value1&name2=value2
     * @return 返回结果
     */
    public static String sendGet(String url, String param) {
        if (StringUtils.isNotEmpty(param)) {
            url = url + "?" + param;
        }

        return sendRequest(METHOD_GET, url, null, null, null);
    }

    /**
     * 发送GET请求
     * @param url 请求URL
     * @param paramMap 请求参数
     * @return 返回结果
     */
    public static String sendGetWithBody(String url, Map<String, Object> paramMap) {
        return sendGetWithBody(url, paramMap, null);
    }

    /**
     * 发送GET请求
     * @param url 请求URL
     * @param paramMap 请求参数
     * @param headerMap 请求头
     * @return 返回结果
     */
    public static String sendGetWithBody(String url, Map<String, Object> paramMap, Map<String, String> headerMap) {
        return sendRequest(METHOD_GET, url, paramMap, headerMap, CONTENT_TYPE_APPLICATION_JSON);
    }

    /**
     * 发送POST请求
     * @param url 请求URL
     * @param paramMap 请求参数
     * @return 返回结果
     */
    public static String sendPost(String url, Map<String, Object> paramMap) {
        return sendRequest(METHOD_POST, url, paramMap, null, CONTENT_TYPE_APPLICATION_JSON);
    }

    /**
     * 发送POST请求
     * @param url 请求URL
     * @param paramMap 请求参数
     * @param headerMap 请求头
     * @return 返回结果
     */
    public static String sendPost(String url, Map<String, Object> paramMap, Map<String, String> headerMap) {
        return sendRequest(METHOD_POST, url, paramMap, headerMap, CONTENT_TYPE_APPLICATION_JSON);
    }

    /**
     * 发送HTTP请求
     * @param requestMethod 请求方式(GET/POST)
     * @param url 请求URL
     * @param paramMap 请求参数
     * @param headerMap 请求头
     * @param contentType contentType
     * @return 返回结果
     */
    public static String sendRequest(String requestMethod, String url, Map<String, Object> paramMap, Map<String, String> headerMap, String contentType) {
        String param = "";
        if (paramMap != null && !paramMap.isEmpty()) {
            param = JsonUtils.obj2JsonStr(paramMap);
        }

        HttpRequest.Builder requestBuilder = HttpRequest.newBuilder().uri(URI.create(url));
        if (headerMap != null && !headerMap.isEmpty()) {
            headerMap.forEach(requestBuilder::header);
        }
        if (StringUtils.isNotEmpty(contentType)) {
            requestBuilder.header("Content-Type", contentType);
        }
        HttpRequest request = requestBuilder
                .method(requestMethod, StringUtils.isEmpty(param)
                        ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(param))
                .build();
        try {
            HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
            return response.body();
        } catch (Exception e) {
            log.error("发送{}请求失败！请求url:{},param:{},header:{}", requestMethod, url, param, headerMap);
        }

        return null;
    }
}
